package cn.tedu.charging.order.service.impl;

import cn.tedu.charging.common.constant.MqttConstants;
import cn.tedu.charging.common.pojo.vo.JsonResult;
import cn.tedu.charging.common.constant.Constants;
import cn.tedu.charging.common.pojo.param.GunStatusUpdateParam;
import cn.tedu.charging.common.pojo.vo.StationInfoVO;
import cn.tedu.charging.common.pojo.vo.UserInfoVO;
import cn.tedu.charging.common.utils.JsonUtils;
import cn.tedu.charging.order.feign.DeviceClient;
import cn.tedu.charging.order.feign.UserClient;
import cn.tedu.charging.order.mqtt.MqttProducer;
import cn.tedu.charging.order.pojo.dto.ChargingDTO;
import cn.tedu.charging.order.pojo.dto.OrderMqDTO;
import cn.tedu.charging.order.pojo.dto.StationInfoDTO;
import cn.tedu.charging.order.pojo.dto.UserInfoDTO;
import cn.tedu.charging.order.pojo.param.OrderAddParam;
import cn.tedu.charging.order.quarz.DeviceCheckJob;
import cn.tedu.charging.order.rabbit.RabbitMqProducer;
import cn.tedu.charging.order.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private DeviceClient deviceClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    private MqttProducer mqttProducer;
    @Autowired
    private RabbitMqProducer rabbitMqProducer;
    @Override
    public String createOrder(OrderAddParam orderAddParam) {
        // 1.生成订单号
        String orderNo = getOrderNo();
        // 2.获取场站信息和设备信息
        StationInfoDTO stationInfoDTO = getStationInfoByGunId(orderAddParam.getGunId());
        // 3.获取用户信息
        UserInfoDTO userInfoDTO = getUserInfoByUerId(orderAddParam.getUserId());
        // 4.给设备发送开始充电指令
        try {
            new DeviceCheckJob(orderNo,orderAddParam.getGunId());
        } catch (SchedulerException e) {
           log.error("设备自检任务创建失败");
        }
        startCharging(orderNo,orderAddParam.getPileId(),orderAddParam.getGunId());
        // 5.修改充电桩状态为充电中
        Boolean success = updateGunStateBusy(orderAddParam.getGunId());
        // 6. 发送消息队列
        OrderMqDTO orderMqDTO = new OrderMqDTO();
        orderMqDTO.setOrderNo(orderNo);
        rabbitMqProducer.sendOrder(orderMqDTO);

        return orderNo;
    }
    private String getOrderNo() {
        return "777";
    }

    private StationInfoDTO getStationInfoByGunId(Integer gunId) {
        JsonResult<StationInfoVO> stationInfo = deviceClient.getStationInfo(1);
        if (stationInfo != null) {
            StationInfoDTO stationInfoDTO = new StationInfoDTO();
            BeanUtils.copyProperties(stationInfo,stationInfoDTO);
            return stationInfoDTO;
        }
        return null;
    }

    private UserInfoDTO getUserInfoByUerId(Integer userId) {
        JsonResult<UserInfoVO> userInfo = userClient.getUserInfo(userId);
        if (userInfo != null) {
            UserInfoDTO userInfoDTO = new UserInfoDTO();
            BeanUtils.copyProperties(userInfo,userInfoDTO);
            return userInfoDTO;
        }
        return null;
    }

    private void startCharging(String orderNo, Integer pileId, Integer gunId) {
        String topic = MqttConstants.TOPIC_START_CHARGING_PREFIX + pileId;
        ChargingDTO chargingDTO = new ChargingDTO();
        chargingDTO.setOrderNo(orderNo);
        chargingDTO.setPileId(pileId);
        chargingDTO.setGunId(gunId);
        chargingDTO.setMsg(Constants.START_CHARGING);
        mqttProducer.send(topic, JsonUtils.toJson(chargingDTO));
    }

    private Boolean updateGunStateBusy(Integer gunId) {
        GunStatusUpdateParam param = new GunStatusUpdateParam();
        param.setGunId(gunId);
        param.setStatus(Constants.GUN_STATUS_BUSY);
        JsonResult<Boolean> booleanJsonResult = deviceClient.updateGunStatus(param);
        if (booleanJsonResult != null) {
            return booleanJsonResult.getData();
        }
        return false;
    }
}
